#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <setjmp.h>
#include "StreamType.h"
#include "test.h"

InOutStreamType InOutStream;
InOutStreamType *InOut = &InOutStream;
static int PrintLevel = 0;
jmp_buf AbnormalEnv;

void PrintLevelAdd(int type)
{
    if (type == T_Print) {
        PrintLevel++;
    }
}

void PrintLevelSub(int type)
{
    if (type == T_Print) {
        PrintLevel--;
    }
}

void PrintLabelKey(const char *key, int type)
{
    if (type != T_Print) return;
    int i;
    printf("\n");
    for (i = 0; i < PrintLevel; i++) {
        printf("\t");
    }
    printf("%s:\t", key);
}

void PrintLabelValue(const char *val, int type)
{
    if (type == T_Print) {
        printf("%s", val);
    }
}

void PrintLabelEndKey(int type)
{
}

void ThrowError(int errCode)
{
    longjmp(AbnormalEnv, errCode);
}

void Log(int type, const char *format, ...)
{
    static const char *tag[] = {"Verbose", "Debug", "Info", "Warning", "Error"};
    printf("%s:\t", tag[type]);

    va_list arg;
    va_start(arg, format);
    vprintf(format, arg);
    va_end(arg);

    printf("\n");
}

static void ReadFile(const char *path)
{
    FILE *fp = fopen(path, "rb");
    if (fp == NULL) {
        fprintf(stderr, "%s: %s", strerror(errno), path);
        ThrowError(- __LINE__);
    }
    fseek(fp, 0, SEEK_END);
    InOutStream.len = (int) ftell(fp);
    fseek(fp, 0, SEEK_SET);
    InOutStream.buf = (unsigned char*) ST_Alloc(InOutStream.len);
    InOutStream.len = fread(InOutStream.buf, 1, InOutStream.len, fp);
    fclose(fp);
}

int main()
{
    #ifndef ReadAndPrintOnly
    TEST_ROOT root;
    #endif // ReadAndPrintOnly
    const char *path = "1.exe";

    printf("run start\n");
    int ret = setjmp(AbnormalEnv);
    if (ret < 0) {
        fprintf(stderr, "System run error at %d line\n", -ret);
    } else if (ret > 0) {
        fprintf(stderr, "Stream run error at %d line\n", ret);
    } else {
        ReadFile(path);
        PrintLabelKey("root", T_Print);
        #ifdef ReadAndPrintOnly
        PauseAll(NULL, T_Print);
        #else // ifndef ReadAndPrintOnly
        PauseAll(&root, T_Read);
        PauseAll(&root, T_Print);
        #endif // ReadAndPrintOnly
        printf("\n");
    }

    printf("run stop\n");
    ST_FreeAll();
    return ret;
}
